package com.snow.common.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.snow.annotation.RequireLogin;
import com.snow.annotation.RequirePermission;
import com.snow.component.SystemConfigComponent;
import com.snow.conditions.*;
import com.snow.jpa.ITenant;
import com.snow.jpa.model.BasePageParams;
import com.snow.jpa.model.IBaseSearchParams;
import com.snow.model.IdParams;
import com.snow.common.entity.SystemConfigEntity;
import com.snow.common.entity.SystemConfigItemEntity;
import com.snow.common.service.SystemConfigItemService;
import com.snow.common.service.SystemConfigService;
import com.snow.service.IAuthComponent;
import com.snow.view.PageData;
import com.snow.view.WebResponse;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/system-config")
public class SystemConfigController {

    private final SystemConfigService systemconfigService;
    private final SystemConfigComponent systemConfigComponent;
    private final SystemConfigItemService systemConfigItemService;
    private final IAuthComponent authComponent;

    public SystemConfigController(SystemConfigService systemconfigService, SystemConfigComponent systemConfigComponent, SystemConfigItemService systemConfigItemService, @Autowired(required = false) IAuthComponent authComponent) {
        this.systemconfigService = systemconfigService;
        this.systemConfigComponent = systemConfigComponent;
        this.systemConfigItemService = systemConfigItemService;
        this.authComponent = authComponent;
    }

    @Getter
    @Setter
    @QueryDescription(sort = @Order(value = "createTime", type = QueryOrderType.desc))
    public static class PageParams extends BasePageParams {
        @QueryConditionField(type = ConditionType.like)
        private String name;
        @QueryConditionField
        private Integer type;
    }

    @PostMapping("/page")
    public WebResponse<PageData<SystemConfigEntity>> page(@RequestBody PageParams params) {
        PageData<SystemConfigEntity> ret = systemconfigService.page(params);
        return WebResponse.success(ret);
    }

    @RequirePermission("system-config:create")
    @PostMapping("/create")
    public WebResponse<SystemConfigEntity> create(@RequestBody SystemConfigEntity entity) {
        return WebResponse.success(systemconfigService.save(entity));
    }

    @PostMapping("/details")
    public WebResponse<SystemConfigEntity> details(@RequestBody IdParams params) {
        SystemConfigEntity config = systemconfigService.get(params.getId());
        if (config.getConfigType() == 1) {
            config.setConfig(systemConfigComponent.getConfig(params.getId()).orElse(null));
        } else {
            config.setDictItems(systemConfigComponent.getConfigs(params.getId(), null));
        }
        return WebResponse.success(config);
    }


    @PostMapping("/search-details")
    public WebResponse<List<SystemConfigEntity>> searchDetails(@RequestBody SearchParams params) {
        List<SystemConfigEntity> configEntities = systemconfigService.search(params);
        for (SystemConfigEntity configEntity : configEntities) {
            if (configEntity.getConfigType() == 1) {
                configEntity.setConfig(systemConfigComponent.getConfig(configEntity.getId()).orElse(null));
            } else {
                configEntity.setDictItems(systemConfigComponent.getConfigs(configEntity.getId(), null));
            }
        }
        JSONObject entries = new JSONObject();
        for (SystemConfigEntity configEntity : configEntities) {
            if (configEntity.getConfigType() == 1) {
                SystemConfigItemEntity config = configEntity.getConfig();
                if (config == null) {
                    entries.set(configEntity.getCode(), StrUtil.blankToDefault(configEntity.getDefaultValue(), ""));
                } else {
                    entries.set(configEntity.getCode(), StrUtil.blankToDefault(config.getConfigValue(), ""));
                }
            } else {
                if (configEntity.getDictItems() == null || configEntity.getDictItems().isEmpty()) {
                    entries.set(configEntity.getCode(), new ArrayList<>(0));
                } else {
                    List<String> values = configEntity.getDictItems().stream().map(SystemConfigItemEntity::getConfigValue).collect(Collectors.toList());
                    entries.set(configEntity.getCode(), values);
                }
            }
        }
        return WebResponse.success(configEntities).setExt(entries);
    }

    @PostMapping("/details-by-obj-id")
    public WebResponse<SystemConfigEntity> detailsByObjId(@RequestBody SystemConfigItemEntity params) {
        if (StrUtil.isBlank(params.getConfigObjId())) {
            return WebResponse.fail("configObjId不能为空");
        }
        SystemConfigEntity config = systemconfigService.get(params.getId());
        if (config.getConfigType() == 1) {
            config.setConfig(systemConfigComponent.getConfig(params.getId(), params.getConfigObjId()).orElse(null));
        } else {
            config.setDictItems(systemConfigComponent.getConfigs(params.getId(), params.getConfigObjId()));
        }
        return WebResponse.success(config);
    }

    @RequirePermission("system-config:config")
    @PostMapping("/config")
    public WebResponse<Void> config(HttpServletRequest request, @RequestBody SystemConfigItemEntity configParams) {
        systemconfigService.config(configParams, request.getHeader("x-domain"));
        return WebResponse.success();
    }

    @PostMapping("/config-by-obj-id")
    public WebResponse<Void> configByObjId(HttpServletRequest request, @RequestBody SystemConfigItemEntity configParams) {
        if (StrUtil.isBlank(configParams.getConfigObjId())) {
            return WebResponse.fail("配置对象主键不能为空");
        }
        systemconfigService.config(configParams, request.getHeader("x-domain"));
        return WebResponse.success();
    }


    @PostMapping("/update")
    @RequirePermission("system-config:update")
    public WebResponse<SystemConfigEntity> update(@RequestBody SystemConfigEntity entity) {
        return WebResponse.success(systemconfigService.update(entity));
    }

    @PostMapping("/delete")
    @RequirePermission("system-config:delete")
    public WebResponse<SystemConfigEntity> delete(@RequestBody IdParams params) {
        return WebResponse.success(systemconfigService.delete(params.getId()));
    }

    @Getter
    @Setter
    public static class SearchParams implements IBaseSearchParams {
        @QueryConditionField(type = ConditionType.in, value = "id")
        Integer[] ids;
        @QueryConditionField(type = ConditionType.in, value = "code")
        String[] codes;
        @QueryConditionField(type = ConditionType.in, value = "type")
        String[] types;
    }

    @PostMapping("/search")
    public WebResponse<List<SystemConfigEntity>> search(@RequestBody SearchParams params) {
        return WebResponse.success(systemconfigService.search(params));
    }

    @Getter
    @Setter
    public static class SearchConfigDetailsParams implements IBaseSearchParams {
        @QueryConditionField(type = ConditionType.in, value = "type")
        Integer[] types;
    }

    /**
     * 获取所有可配置项，以及配置值
     */
    @PostMapping("/search-configs-details")
    public WebResponse<List<SystemConfigEntity>> searchConfigsDetails(@RequestBody SearchConfigDetailsParams params) {
        return WebResponse.success(systemconfigService.searchConfigsDetails(params));
    }

    @RequireLogin(false)
    @GetMapping("/load-configs-by-subdomain")
    public WebResponse<JSONObject> loadConfigsBySubdomain(HttpServletRequest request) {
        ITenant tenant = authComponent.findTenant(request.getHeader("x-domain"));
        if (tenant == null) {
            log.error("无法根据域名找到租户信息，访问域名：{}", request.getHeader("x-domain"));
            return WebResponse.fail("无法根据域名找到租户信息，请联系管理员");
        }
        List<SystemConfigEntity> configs = systemconfigService.findAllBy("type", 4);
        List<SystemConfigItemEntity> configItems = systemConfigItemService.lambdaQuery().in("configObjId", request.getHeader("x-domain")).findAll();
        JSONObject retConfig = new JSONObject();
        for (SystemConfigEntity config : configs) {
            if (config.getConfigType() == 1) {
                Optional<SystemConfigItemEntity> optionalFirst = configItems.stream().filter(i -> i.getConfigId().equals(config.getId())).findFirst();
                config.setConfig(optionalFirst.orElse(null));
                if (optionalFirst.isPresent()) {
                    retConfig.set(config.getCode(), optionalFirst.get().getConfigValue());
                } else {
                    retConfig.set(config.getCode(), config.getDefaultValue());
                }
            } else {
                config.setDictItems(configItems.stream().filter(i -> i.getConfigId().equals(config.getId())).collect(Collectors.toList()));
                retConfig.set(config.getCode(), config.getDictItems());
            }
        }
        retConfig.set("tenant", tenant);
        return WebResponse.success(retConfig);
    }
}
